import requests
import pandas as pd
from datetime import datetime, timedelta, date
import logging
from typing import Dict, List, Optional
from backend.config.weather_config import WeatherConfig

logger = logging.getLogger(__name__)

class WeatherAPIService:
    """气象数据API服务"""
    
    def __init__(self, visualcrossing_api_key: Optional[str] = None):
        # 从配置文件获取API密钥
        if visualcrossing_api_key is None:
            self.visualcrossing_api_key = WeatherConfig.get_visualcrossing_api_key()
        else:
            self.visualcrossing_api_key = visualcrossing_api_key
            
        # 从配置文件获取坐标
        self.lat, self.lon = WeatherConfig.BELGIUM_LAT, WeatherConfig.BELGIUM_LON
        
    def get_weather_data(self, start_date: str, end_date: str) -> Optional[pd.DataFrame]:
        """
        获取气象数据，根据日期选择不同的API
        
        Args:
            start_date: 开始日期 (YYYY-MM-DD)
            end_date: 结束日期 (YYYY-MM-DD)
        
        Returns:
            DataFrame包含气象数据
        """
        try:
            start_dt = datetime.strptime(start_date, '%Y-%m-%d').date()
            end_dt = datetime.strptime(end_date, '%Y-%m-%d').date()
            today = datetime.now().date()
            
            # 如果请求的日期包含前一天，使用VisualCrossing
            if start_dt < today:
                logger.info(f"使用VisualCrossing API获取历史气象数据: {start_date} 到 {end_date}")
                return self._get_weather_from_visualcrossing(start_date, end_date)
            else:
                logger.info(f"使用OpenMeteo API获取当前/未来气象数据: {start_date} 到 {end_date}")
                return self._get_weather_from_openmeteo(start_date, end_date)
                
        except Exception as e:
            logger.error(f"获取气象数据失败: {e}")
            return None
    
    def _get_weather_from_visualcrossing(self, start_date: str, end_date: str) -> Optional[pd.DataFrame]:
        """使用VisualCrossing API获取历史气象数据"""
        try:
            url = "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline"
            params = {
                'location': f"{self.lat},{self.lon}",
                'start': start_date,
                'end': end_date,
                'unitGroup': 'metric',
                'include': 'days',
                'key': self.visualcrossing_api_key,
                'contentType': 'json'
            }
            
            logger.info(f"请求VisualCrossing API: {start_date} 到 {end_date}")
            response = requests.get(url, params=params, timeout=30)
            
            if response.status_code != 200:
                logger.error(f"VisualCrossing API请求失败: {response.status_code} - {response.text}")
                return None
            
            data = response.json()
            
            if 'days' not in data:
                logger.error("VisualCrossing数据格式错误")
                return None
            
            # 转换为DataFrame
            weather_data = []
            for day in data['days']:
                weather_data.append({
                    'dt': datetime.strptime(day['datetime'], '%Y-%m-%d').date(),
                    't_max': day.get('tempmax', 20.0),
                    't_min': day.get('tempmin', 10.0),
                    'prec_sum': day.get('precip', 0.0),
                    'humidity': day.get('humidity', 70.0),
                    'pressure': day.get('pressure', 1013.0),
                    'wind_dir': day.get('winddir', 180.0),
                    'ws_max': day.get('windspeed', 10.0),
                    'uv_index': day.get('uvindex', 3.0),
                    'snow': day.get('snow', 0.0),
                    'sun_dur': day.get('sunshineDuration', 8.0) / 3600 if day.get('sunshineDuration') else 8.0,  # 转换为小时
                    'sw_rad': day.get('solarradiation', 10.0),
                    'et0': day.get('evapotranspiration', 2.0) if day.get('evapotranspiration') else 2.0
                })
            
            df = pd.DataFrame(weather_data)
            logger.info(f"成功从VisualCrossing获取 {len(df)} 条气象数据")
            return df
            
        except Exception as e:
            logger.error(f"从VisualCrossing获取气象数据失败: {e}")
            return None
    
    def _get_weather_from_openmeteo(self, start_date: str, end_date: str) -> Optional[pd.DataFrame]:
        """使用OpenMeteo API获取当前/未来气象数据"""
        try:
            url = "https://archive-api.open-meteo.com/v1/archive"
            params = {
                'latitude': self.lat,
                'longitude': self.lon,
                'start_date': start_date,
                'end_date': end_date,
                'daily': 'temperature_2m_max,temperature_2m_min,precipitation_sum,relative_humidity_2m_max,pressure_msl,wind_direction_10m_dominant,wind_speed_10m_max,uv_index_max,snowfall_sum,sunshine_duration,shortwave_radiation_sum,reference_evapotranspiration',
                'timezone': 'Europe/Brussels'
            }
            
            logger.info(f"请求OpenMeteo API: {start_date} 到 {end_date}")
            response = requests.get(url, params=params, timeout=30)
            
            if response.status_code != 200:
                logger.error(f"OpenMeteo API请求失败: {response.status_code}")
                return None
            
            data = response.json()
            
            if 'daily' not in data:
                logger.error("OpenMeteo数据格式错误")
                return None
            
            # 转换为DataFrame
            weather_data = []
            dates = data['daily']['time']
            t_max = data['daily']['temperature_2m_max']
            t_min = data['daily']['temperature_2m_min']
            precip = data['daily']['precipitation_sum']
            humidity = data['daily'].get('relative_humidity_2m_max', [70] * len(dates))
            pressure = data['daily'].get('pressure_msl', [1013] * len(dates))
            wind_dir = data['daily'].get('wind_direction_10m_dominant', [180] * len(dates))
            wind_speed = data['daily'].get('wind_speed_10m_max', [10] * len(dates))
            uv_index = data['daily'].get('uv_index_max', [3] * len(dates))
            snow = data['daily'].get('snowfall_sum', [0] * len(dates))
            sun_dur = data['daily'].get('sunshine_duration', [28800] * len(dates))  # 秒转小时
            sw_rad = data['daily'].get('shortwave_radiation_sum', [10] * len(dates))
            et0 = data['daily'].get('reference_evapotranspiration', [2] * len(dates))
            
            for i, date_str in enumerate(dates):
                weather_data.append({
                    'dt': datetime.strptime(date_str, '%Y-%m-%d').date(),
                    't_max': t_max[i],
                    't_min': t_min[i],
                    'prec_sum': precip[i],
                    'humidity': humidity[i] if i < len(humidity) else 70,
                    'pressure': pressure[i] if i < len(pressure) else 1013,
                    'wind_dir': wind_dir[i] if i < len(wind_dir) else 180,
                    'ws_max': wind_speed[i] if i < len(wind_speed) else 10,
                    'uv_index': uv_index[i] if i < len(uv_index) else 3,
                    'snow': snow[i] if i < len(snow) else 0,
                    'sun_dur': sun_dur[i] / 3600 if i < len(sun_dur) else 8,  # 转换为小时
                    'sw_rad': sw_rad[i] if i < len(sw_rad) else 10,
                    'et0': et0[i] if i < len(et0) else 2
                })
            
            df = pd.DataFrame(weather_data)
            logger.info(f"成功从OpenMeteo获取 {len(df)} 条气象数据")
            return df
            
        except Exception as e:
            logger.error(f"从OpenMeteo获取气象数据失败: {e}")
            return None
    
    def validate_apis(self) -> Dict[str, bool]:
        """验证两个API是否可用"""
        results = {}
        
        # 验证VisualCrossing API
        try:
            yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
            test_df = self._get_weather_from_visualcrossing(yesterday, yesterday)
            results['visualcrossing'] = test_df is not None and not test_df.empty
        except Exception as e:
            logger.error(f"VisualCrossing API验证失败: {e}")
            results['visualcrossing'] = False
        
        # 验证OpenMeteo API
        try:
            today = datetime.now().strftime('%Y-%m-%d')
            test_df = self._get_weather_from_openmeteo(today, today)
            results['openmeteo'] = test_df is not None and not test_df.empty
        except Exception as e:
            logger.error(f"OpenMeteo API验证失败: {e}")
            results['openmeteo'] = False
        
        return results 